package cn.com.dcsgo.controller;

import cn.com.dcsgo.ServiceUserApp;
import cn.com.dcsgo.constant.RedisConst;
import cn.com.dcsgo.enums.UserType;
import cn.com.dcsgo.exception.UuPreferredException;
import cn.com.dcsgo.model.user.User;
import cn.com.dcsgo.result.Result;
import cn.com.dcsgo.result.ResultCodeEnum;
import cn.com.dcsgo.security.AuthContextHolder;
import cn.com.dcsgo.service.UserService;
import cn.com.dcsgo.util.ConstantPropertiesUtil;
import cn.com.dcsgo.util.HttpClientUtils;
import cn.com.dcsgo.util.jwt.JwtHelper;
import cn.com.dcsgo.vo.user.LeaderAddressVo;
import cn.com.dcsgo.vo.user.UserLoginVo;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * MiniAppApiController
 *
 * @author Dcsgo
 * @since 2025/4/24 6:10
 */
@Slf4j
@Api(tags = "用户")
@RequiredArgsConstructor
@RestController
@RequestMapping("weixin/user")
public class MiniAppApiController {
    private final UserService userService;
    private final RedisTemplate<Object, Object> redisTemplate;

    @ApiOperation(value = "登录", notes = "code 是微信临时登录凭证，参考：https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html")
    @GetMapping("login/{code}")
    public Result<Map<String, Object>> login(@PathVariable String code) {
        if (StringUtils.isEmpty(code)) {
            throw new UuPreferredException(ResultCodeEnum.ILLEGAL_CALLBACK_REQUEST_ERROR);
        }
        //通过 code 获取 openid(微信用户唯一标识)
        String wecatRequestUrl = "https://api.weixin.qq.com/sns/jscode2session" +
                "?appid=%s" +
                "&secret=%s" +
                "&js_code=%s" +
                "&grant_type=authorization_code";
        String requestUrl = String.format(
                wecatRequestUrl,
                ConstantPropertiesUtil.WX_APP_ID,
                ConstantPropertiesUtil.WX_APP_SECRET,
                code);
        String response;
        try {
            response = HttpClientUtils.get(requestUrl);
        } catch (Exception e) {
            throw new UuPreferredException(ResultCodeEnum.FETCH_ACCESS_TOKEN_FAIL);
        }
        JSONObject responseJson = JSONObject.parseObject(response);
        if (responseJson.getString("errcode") != null) {
            throw new UuPreferredException(ResultCodeEnum.FETCH_ACCESS_TOKEN_FAIL);
        }
        String openId = responseJson.getString("openid");

        //根据openid查询数据库，不存在需要添加到数据库中
        User user = userService.getByOpenId(openId);
        if (user == null) {
            user = new User();
            user.setOpenId(openId);
            user.setNickName(openId);
            user.setPhotoUrl("");
            user.setUserType(UserType.USER);
            user.setIsNew(0);
            userService.save(user);
        }
        //存在查询默认自提点和团长信息
        LeaderAddressVo leaderAddressVo = userService.getLeaderAndDeliveryInfo(user.getId());

        //使用JWT生成token
        String token = JwtHelper.createToken(user.getId(), user.getNickName());

        //将用户信息添加到 redis 中
        UserLoginVo userLoginVo = userService.getUserLoginVo(user.getId());
        log.debug("userLoginVo:{}", userLoginVo);
        redisTemplate.opsForValue().set(
                RedisConst.USER_LOGIN_KEY_PREFIX + user.getId(),
                userLoginVo,
                RedisConst.USER_KEY_TIMEOUT,
                TimeUnit.DAYS);

        //封装要返回的数据
        Map<String, Object> result = new HashMap<>();
        result.put("user", user);
        result.put("token", token);
        result.put("leaderAddressVo", leaderAddressVo);

        return Result.ok(result);
    }

    @ApiOperation("更新用户信息")
    @PostMapping("auth/updateUser")
    public Result<ServiceUserApp> update(@RequestBody User user) {
        if (user.getId() == null) {
            user.setId(AuthContextHolder.getUserId());
        }
        log.debug("user:{}", user);
        userService.updateById(user);
        return Result.ok(null);
    }

}
